﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Baosight.Platform.Core.UI.Controls;
using Telerik.Windows.Controls;
using Telerik.Windows.Controls.Charting;
using Baosight.Platform.Core;
using Baosight.Platform.Core.ServiceModel;
using Baosight.ZNH.ZMCA.UI.Utils;
using Baosight.ZNH.ZMCA.UI.Model;

namespace Baosight.ZNH.ZMCA.UI
{
    public partial class ZMCA25 : EFView
    {
        private IDictionary<string, string> materialDic = new Dictionary<string, string>();
        private string sortIndexFlag = "";

        public ZMCA25()
        {
            InitializeComponent();
            TrendChart.DefaultView.ChartLegend.Header = string.Empty;
        }

        /// <summary>
        /// 初始化界面控件
        /// </summary>
        /// <param name="initData"></param>
        public override void Initialize(EIInfo initData)
        {
            base.Initialize(initData);
            this.fdAnalysisType.Value = "1";
            EIBlock block = initData.GetBlock("cmes.ca.materialtype");
            materialDic.Clear();
            foreach (var item in block.Rows)
            {
                materialDic.Add(item["value"].ToString(), item["display"].ToString());
            }
        }

        #region 页面事件响应

        /// <summary>
        /// 分析类型选择事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void fdAnalysisType_ValueChanged(object sender, ValueChangedEventArgs e)
        {
            string val = Common.GetStringValue(this.fdAnalysisType.Value);

            if (val.Trim() == string.Empty)
                return;

            switch (val)
            {
                case "0":       //超节率
                    this.fdMaterialType.Visibility = Visibility.Collapsed;
                    break;
                case "1":       //消耗量
                    this.fdMaterialType.Visibility = Visibility.Visible;
                    break;
                default:
                    this.fdMaterialType.Visibility = Visibility.Collapsed;
                    break;
            }


        }

        /// <summary>
        /// “分析”按钮响应事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public override void OnQueryButtonClick(object sender, RoutedEventArgs e)
        {
            string analyType = this.fdAnalysisType.Value == null ? "" : this.fdAnalysisType.Value.ToString().Trim();

            if (analyType.Equals("0"))      //超节率
            {
                QueryByMaterialRate();
            }
            else if (analyType.Equals("1"))     //消耗量
            {
                if (this.fdMaterialType.Value == null || this.fdMaterialType.Value.ToString().Trim().Equals(""))
                {
                    EFWindow.Alert("请选择材料类型！");
                    return;
                }
                else
                {
                    QueryByMaterialConsumption();
                }
            }
        }

        #endregion

        #region 分析数据查询及处理

        /// <summary>
        /// 按照超节率查询
        /// </summary>
        private void QueryByMaterialRate()
        {
            EIInfo eiInfo = new EIInfo();

            eiInfo.AddBlock(this.GetQueryBlock("Rate"));
            eiInfo.Set(EIConstants.ServiceNameKey, "ZMCA25");
            eiInfo.Set(EIConstants.MethodNameKey, "queryByRate");

            HttpServiceAgent agent = new HttpServiceAgent();
            agent.CallService(eiInfo, QueryByMaterialRateDoWorkCompleted);
        }

        /// <summary>
        ///  获取查询条件
        /// </summary>
        /// <returns></returns>
        private EIBlock GetQueryBlock(string index)
        {
            EIBlock block = new EIBlock(EIConstants.QueryStatusBlock);
            EIRow row = new EIRow();

            row.Add("fdFromYear", datePicker.FromDate.Year.ToString());
            row.Add("fdFromMonth", datePicker.FromDate.Month.ToString());
            row.Add("fdToYear", datePicker.ToDate.Year.ToString());
            row.Add("fdToMonth", datePicker.ToDate.Month.ToString());

            if (index.Equals("Rate"))
            {
                Common.AddEIColumnsToEIBlock(block, new string[] { "fdToYear", "fdToMonth", "fdFromYear", "fdFromMonth"});
                sortIndexFlag = "Rate";
            }
            else if (index.Equals("Amount"))
            {
                Common.AddEIColumnsToEIBlock(block, new string[] { "fdToYear", "fdToMonth", "fdFromYear", "fdFromMonth", 
                "fdMaterialType"});
                row.Add("fdMaterialType", fdMaterialType.Value);
                sortIndexFlag = "Amount";
            }

            block.AddRow(row);
            
            return block;
        }

        /// <summary>
        /// 按照超节率查询回调函数
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void QueryByMaterialRateDoWorkCompleted(object sender, DoWorkCompletedEventArgs e)
        {
            if (e.EIInfo.Status == -1)
            {
                return;
            }
            else
            {
                EIInfo outInfo = e.EIInfo;
                EIBlock plan = outInfo.GetBlock("departmentPlan");
                EIBlock actual = outInfo.GetBlock("departmentActual");

                if ((plan == null) || (actual == null) || (plan.GetRowCount() <= 0) || (actual.GetRowCount() <= 0))
                {
                    return;
                }
                else
                {
                    IList<EIRow> lstRate = new List<EIRow>();
                    lstRate = CalculateMaterialRate(plan, actual);
                    InitChart(true);
                    ShowDataToChart(lstRate, true);
                }
            }
        }

        /// <summary>
        /// 组装数据，计算超节率
        /// </summary>
        /// <param name="plan"></param>
        /// <param name="actual"></param>
        /// <returns></returns>
        private IList<EIRow> CalculateMaterialRate(EIBlock plan, EIBlock actual)
        {
            IDictionary<string, EIRow> dic = new Dictionary<string, EIRow>();
            IList<EIRow> list = new List<EIRow>();     //用于累计运算
            IList<EIRow> dest = new List<EIRow>();     //用于排序

            //Linq排序
            //var sortedList0 = (from it in plan.Rows orderby it["fdPrice"] select it).ToList<EIRow>();  //升序
            //var sortedList1 = (from it in plan.Rows orderby it["fdPrice"] descending select it).ToList<EIRow>();   //降序

            foreach (var item in plan.Rows)     //添加计划消耗
            {
                string itemUniqueName = Common.GetStringValue(item["fdKeyId"]);

                if (itemUniqueName.Trim() == string.Empty)
                    continue;

                if (!dic.ContainsKey(itemUniqueName))
                {
                    string planPrice = item["fdPrice"] == null ? "0.0" : item["fdPrice"].ToString().Trim();

                    item.Add("planPrice", planPrice);
                    dic.Add(itemUniqueName, item);
                }
            }

            foreach (var item in actual.Rows)      //添加实际消耗
            {
                string itemUniqueName = Common.GetStringValue(item["fdKeyId"]);

                if (itemUniqueName.Trim() == string.Empty)
                    continue;

                EIRow row = dic[itemUniqueName];
                string actualPrice = item["fdPrice"] == null ? "0.0" : item["fdPrice"].ToString().Trim();
                row.Add("actualPrice", actualPrice);

                list.Add(Common.CloneRow(row, new string[] { "fdKeyId", "fdName", "fdLevel","fdParentId", 
                                                             "planPrice", "actualPrice" }));
            }

            foreach (var item in dic.Values)       //计算超节率
            {
                if (Common.GetIntValue(item["fdLevel"]) == 2)    //只对LEVEL = 2的层级进行累加)
                    AddUpToBase(item, list);
                
                double planValue = Convert.ToDouble(item["planPrice"].ToString());
                double actualValue = Convert.ToDouble(item["actualPrice"].ToString());

                if ((IsValidate(planValue)) && (IsValidate(actualValue)))
                {
                    double rate = Math.Abs(actualValue / planValue - 1);
                    item.Add("rate", rate);
                }
                else
                {
                    if (IsValidate(actualValue))
                    {
                        item.Add("rate", 1.0);
                    }
                    else
                    {
                        item.Add("rate", 0.0);
                    }
                }

                dest.Add(item);
            }

            var sortedList = (from it in dest orderby Common.GetDoubleValue(it["rate"])
                               select it).ToList<EIRow>();  //按照超节率升序排列

            return sortedList;
        }

        /// <summary>
        /// 累加函数(递归调用)
        /// </summary>
        /// <param name="item"></param>
        /// <param name="list"></param>
        private void AddUpToBase(EIRow item, IList<EIRow> list)
        {
            string fdKeyId = item["fdKeyId"].ToString().Trim();
            var childItems = (from element in list where (element["fdParentId"] != null) &&
                              (element["fdParentId"].ToString().Trim().Equals(fdKeyId))
                              select element).ToList<EIRow>();

            IList<EIRow> newCopy = new List<EIRow>();   //克隆一份新的List，防止源list被改变
            foreach (var element in childItems)
            {
                newCopy.Add(Common.CloneRow(element, new string[] { "fdKeyId", "fdName", "fdLevel","fdParentId", 
                                                                    "planPrice", "actualPrice" }));
            }

            foreach (var it in childItems)
            {
                AddUpToBase(it, list);

                double planValue =  Common.GetDoubleValue(item["planPrice"].ToString());
                double actualValue = Common.GetDoubleValue(item["actualPrice"].ToString());
                double pValue = Common.GetDoubleValue(it["planPrice"].ToString());
                double aValue = Common.GetDoubleValue(it["actualPrice"].ToString());

                item.Add("planPrice", planValue + pValue);
                item.Add("actualPrice", actualValue + aValue);
            }
        }

        /// <summary>
        /// 按照消耗量查询
        /// </summary>
        private void QueryByMaterialConsumption()
        {
            EIInfo eiInfo = new EIInfo();

            eiInfo.AddBlock(this.GetQueryBlock("Amount"));
            eiInfo.Set(EIConstants.ServiceNameKey, "ZMCA25");
            eiInfo.Set(EIConstants.MethodNameKey, "queryByAmount");

            HttpServiceAgent agent = new HttpServiceAgent();
            agent.CallService(eiInfo, QueryByMaterialConsumptionDoWorkCompleted);
        }

        /// <summary>
        /// 按照消耗量查询数据回调函数
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void QueryByMaterialConsumptionDoWorkCompleted(object sender, DoWorkCompletedEventArgs e)
        {
            if (e.EIInfo.Status == -1)
            {
                return;
            }
            else
            {
                EIInfo outInfo = e.EIInfo;
                EIBlock plan = outInfo.GetBlock("departmentPlan");
                EIBlock actual = outInfo.GetBlock("departmentActual");

                if ((plan == null) || (actual == null) || (plan.GetRowCount() <= 0) || (actual.GetRowCount() <= 0))
                {
                    return;
                }
                else
                {
                    IList<EIRow> data = CombineMaterialAmount(plan, actual);

                    InitChart(false);
                    ShowDataToChart(data, false);
                }
            }
        }

        /// <summary>
        /// 组装计划消耗和实际消耗类型数据
        /// </summary>
        /// <param name="plan"></param>
        /// <param name="actual"></param>
        /// <returns></returns>
        private IList<EIRow> CombineMaterialAmount(EIBlock plan, EIBlock actual)
        {
            IDictionary<string, EIRow> dic = new Dictionary<string, EIRow>();
            IList<EIRow> list = new List<EIRow>();     //用于累计运算
            //IList<EIRow> dest = new List<EIRow>();

            foreach (var item in plan.Rows)     //添加计划消耗
            {
                string itemUniqueName = Common.GetStringValue(item["fdKeyId"]);

                if (itemUniqueName.Trim() == string.Empty)
                    continue;

                if (!dic.ContainsKey(itemUniqueName))
                {
                    string planPrice = item["fdPrice"] == null ? "0.0" : item["fdPrice"].ToString().Trim();
                    item.Add("planPrice", planPrice);

                    dic.Add(itemUniqueName, item);
                }
            }

            foreach (var item in actual.Rows)      //添加实际消耗
            {
                string itemUniqueName = Common.GetStringValue(item["fdKeyId"]);

                if (itemUniqueName.Trim() == string.Empty)
                    continue;

                EIRow row = dic[itemUniqueName];
                string actualPrice = item["fdPrice"] == null ? "0.0" : item["fdPrice"].ToString().Trim();
                row.Add("actualPrice", actualPrice);
                list.Add(row);
            }

            foreach (var item in list)      //累计运算
            {
                if (Common.GetIntValue(item["fdLevel"]) == 2)    //只对LEVEL = 2的层级进行累加
                    AddUpToBase(item, list);
            }

            var sortedList = (from it in list orderby Common.GetDoubleValue(it["actualPrice"])
                                  descending select it).ToList<EIRow>();  //降序排列

            return sortedList;
        }

        #endregion

        #region 加载Chart图

        /// <summary>
        /// 初始化Chart图
        /// </summary>
        /// <param name="HasRate"></param>
        private void InitChart(bool HasRate)
        {
            this.TrendChart.SeriesMappings.Clear();

            if (HasRate)
                this.TrendChart.DefaultView.ChartTitle.Content = "材料消耗超节率最小10单位（全矿）";
            else
                this.TrendChart.DefaultView.ChartTitle.Content = materialDic[this.fdMaterialType.Value.ToString()] + "消耗量最大10单位（全矿）";

            this.TrendChart.DefaultView.ChartTitle.FontSize = Common.FontsizeSetting;
            this.TrendChart.DefaultView.ChartArea.FontSize = Common.FontsizeSetting;
            this.TrendChart.DefaultView.ChartLegend.FontSize = Common.FontsizeSetting;

            this.TrendChart.DefaultSeriesDefinition.ShowItemToolTips = true;
            this.TrendChart.DefaultSeriesDefinition.LegendDisplayMode = LegendDisplayMode.SeriesLabel;
            this.TrendChart.DefaultView.ChartLegend.Visibility = System.Windows.Visibility.Visible;
            this.TrendChart.DefaultView.ChartLegend.Header = "单位：万元";

            this.TrendChart.DefaultView.ChartArea.AxisX.LayoutMode = AxisLayoutMode.Inside;
            this.TrendChart.DefaultView.ChartArea.AxisX.AutoRange = true;
            this.TrendChart.DefaultView.ChartArea.AxisX.LabelRotationAngle = 45;

            this.TrendChart.DefaultView.ChartArea.AxisY.AutoRange = true;
            this.TrendChart.DefaultView.ChartArea.AxisY.DefaultLabelFormat = "#VAL ";
            this.TrendChart.DefaultView.ChartArea.AxisY.MajorGridLinesVisibility = Visibility.Visible;
            this.TrendChart.DefaultView.ChartArea.AxisY.MinorGridLinesVisibility = Visibility.Visible;
            this.TrendChart.DefaultView.ChartArea.AxisY.StripLinesVisibility = Visibility.Visible;
            this.TrendChart.DefaultView.ChartArea.AxisY.DefaultLabelFormat = Common.ChartDefaultLabelFormat;

            this.TrendChart.SeriesMappings.Add(GenerateSeriesForChart("计划消耗", 0, "Bar Series"));
            this.TrendChart.SeriesMappings.Add(GenerateSeriesForChart("实际消耗", 1, "Bar Series"));

            this.TrendChart.DefaultView.ChartArea.AdditionalYAxes.Clear();

            if (HasRate)
            {
                this.TrendChart.DefaultView.ChartArea.AdditionalYAxes.Add(new AxisY());
                this.TrendChart.DefaultView.ChartArea.AdditionalYAxes[0].AutoRange = true;
                this.TrendChart.DefaultView.ChartArea.AdditionalYAxes[0].AxisName = "Rate";
                this.TrendChart.DefaultView.ChartArea.AdditionalYAxes[0].Title = "超节率（%）";
                this.TrendChart.DefaultView.ChartArea.AdditionalYAxes[0].MinValue = 0;
                this.TrendChart.DefaultView.ChartArea.AdditionalYAxes[0].MaxValue = 1.1;
                this.TrendChart.DefaultView.ChartArea.AdditionalYAxes[0].Step = 0.1;
                this.TrendChart.DefaultView.ChartArea.AdditionalYAxes[0].DefaultLabelFormat = "#VAL{p0}";

                this.TrendChart.SeriesMappings.Add(GenerateSeriesForChart("超节率", 2, "Bar Series"));
            }
        }

        /// <summary>
        /// 绑定数据显示
        /// </summary>
        /// <param name="sortedList"></param>
        /// <param name="hasRate"></param>
        private void ShowDataToChart(IList<EIRow> sortedList, bool hasRate)
        {
            if (sortedList.Count > 0)
            {
                List<List<ChartData>> itemsSource = new List<List<ChartData>>();
                List<ChartData> lstPlan = new List<ChartData>();
                List<ChartData> lstActual = new List<ChartData>();
                List<ChartData> lstRate = new List<ChartData>();

                if (sortedList.Count > 10)
                {
                    for (int i = 0; i < 10; i++)
                    //for (int i = 0; i < sortedList.Count; i++)
                    {
                        ChartData cdPlan = new ChartData(sortedList[i]["fdName"].ToString(), Common.GetDecimalValue(sortedList[i]["planPrice"]));
                        ChartData cdActual = new ChartData(sortedList[i]["fdName"].ToString(), Common.GetDecimalValue(sortedList[i]["actualPrice"]));

                        lstPlan.Add(cdPlan);
                        lstActual.Add(cdActual);

                        if (hasRate)
                        {
                            ChartData cdRate = new ChartData(sortedList[i]["fdName"].ToString(), Common.GetDecimalValue(sortedList[i]["rate"]));
                            lstRate.Add(cdRate);
                        }
                    }
                }
                else
                {
                    foreach (var item in sortedList)
                    {
                        ChartData cdPlan = new ChartData(item["fdName"].ToString(), Common.GetDecimalValue(item["planPrice"]));
                        ChartData cdActual = new ChartData(item["fdName"].ToString(), Common.GetDecimalValue(item["actualPrice"]));

                        lstPlan.Add(cdPlan);
                        lstActual.Add(cdActual);

                        if (hasRate)
                        {
                            ChartData cdRate = new ChartData(item["fdName"].ToString(), Common.GetDecimalValue(item["rate"]));
                            lstRate.Add(cdRate);
                        }
                    }
                }

                itemsSource.Add(lstPlan);
                itemsSource.Add(lstActual);

                if(hasRate)
                    itemsSource.Add(lstRate);

                this.TrendChart.ItemsSource = itemsSource;
                this.TrendChart.Visibility = System.Windows.Visibility.Visible;
            }
            else
                return;
        }

        /// <summary>
        /// 生成图形形状定义
        /// </summary>
        /// <param name="label"></param>
        /// <param name="index"></param>
        /// <param name="defType"></param>
        /// <returns></returns>
        private SeriesMapping GenerateSeriesForChart(string label, int index, string defType)
        {
            SeriesMapping series = new SeriesMapping();

            switch (defType)
            {
                case "Bar Series":
                    series.SeriesDefinition = new BarSeriesDefinition();
                    break;
                case "Line Series":
                    series.SeriesDefinition = new SplineSeriesDefinition();
                    break;
                default:
                    break;
            }

            if (index == 2)
            {
                series.SeriesDefinition.AxisName = "Rate";
                series.SeriesDefinition.ItemLabelFormat = "#VAL{p0}%";
            }

            series.CollectionIndex = index;
            series.LegendLabel = label;
            series.SeriesDefinition.ShowItemLabels = false;
            series.SeriesDefinition.ShowItemToolTips = true;
            series.SeriesDefinition.ShowZeroValuesLabels = true;
            series.ItemMappings.Add(new ItemMapping("Date", DataPointMember.XCategory));
            series.ItemMappings.Add(new ItemMapping("DataValue", DataPointMember.YValue));
            series.SeriesDefinition.InteractivitySettings.HoverScope = InteractivityScope.Series;
            series.SeriesDefinition.InteractivitySettings.SelectionScope = InteractivityScope.Series;
            series.SeriesDefinition.InteractivitySettings.SelectionMode = ChartSelectionMode.Multiple;
            series.SeriesDefinition.ItemLabelFormat = Common.ChartItemLabelFormat;

            return series;
        }

        #endregion

        #region 辅助函数

        /// <summary>
        /// 判定Double类型是否合法
        /// </summary>
        /// <param name="val"></param>
        /// <returns></returns>
        private bool IsValidate(double val)
        {
            bool result = false;

            if (val >= 0.00001)
            {
                result = true;
            }

            return result;
        }

        #endregion

    }
}
